package cjq.demo.push;

import java.io.BufferedOutputStream;
import java.io.BufferedReader;
import java.io.File;
import java.io.FileInputStream;
import java.io.FileNotFoundException;
import java.io.FileOutputStream;
import java.io.IOException;
import java.io.InputStreamReader;
import java.io.OutputStream;
import java.io.OutputStreamWriter;
import java.io.RandomAccessFile;
import java.util.Arrays;
import java.util.Date;
import java.util.List;
import java.util.zip.Adler32;
import java.util.zip.CheckedOutputStream;

import org.apache.tools.zip.ZipEntry;
import org.apache.tools.zip.ZipOutputStream;

import net.lingala.zip4j.core.ZipFile;
import net.lingala.zip4j.exception.ZipException;
import net.sf.sevenzipjbinding.ExtractOperationResult;
import net.sf.sevenzipjbinding.ISequentialOutStream;
import net.sf.sevenzipjbinding.SevenZip;
import net.sf.sevenzipjbinding.SevenZipException;
import net.sf.sevenzipjbinding.impl.RandomAccessFileInStream;
import net.sf.sevenzipjbinding.simple.ISimpleInArchive;
import net.sf.sevenzipjbinding.simple.ISimpleInArchiveItem;

/**
 * 文件操作工具类
 * @author Administrator
 *
 */
public class FileUtils {
	/**
	 * 获取文件扩展名
	 * 
	 * @param filename
	 * @return
	 */
	public static String getExtend(String filename) {
		return getExtend(filename, "");
	}

	/**
	 * 获取文件扩展名
	 * 
	 * @param filename
	 * @return
	 */
	public static String getExtend(String filename, String defExt) {
		if ((filename != null) && (filename.length() > 0)) {
			int i = filename.lastIndexOf('.');

			if ((i > 0) && (i < (filename.length() - 1))) {
				return (filename.substring(i+1)).toLowerCase();
			}
		}
		return defExt.toLowerCase();
	}

	/**
	 * 获取文件名称[不含后缀名]
	 * 
	 * @param
	 * @return String
	 */
	public static String getFilePrefix(String fileName) {
		int splitIndex = fileName.lastIndexOf(".");
		return fileName.substring(0, splitIndex).replaceAll("\\s*", "");
	}
	
	/**
	 * 获取文件名称[不含后缀名]
	 * 不去掉文件目录的空格
	 * @param
	 * @return String
	 */
	public static String getFilePrefix2(String fileName) {
		int splitIndex = fileName.lastIndexOf(".");
		return fileName.substring(0, splitIndex);
	}
	
	/**
	 * 文件复制
	 *方法摘要：这里一句话描述方法的用途
	 *@param
	 *@return void
	 */
	public static void copyFile(String inputFile,String outputFile) throws FileNotFoundException{
		File sFile = new File(inputFile);
		File tFile = new File(outputFile);
		FileInputStream fis = new FileInputStream(sFile);
		FileOutputStream fos = new FileOutputStream(tFile);
		InputStreamReader in = null;
		OutputStreamWriter out = null;
		int temp = 0;  
		char[] buf = new char[2048];    

        try {  
        	in = new InputStreamReader(fis,"UTF-8");
        	out = new OutputStreamWriter(fos,"UTF-8");
        	while((temp = in.read(buf))!=-1){   
                out.write(buf, 0, temp);   
            }   
        } catch (IOException e) {  
            e.printStackTrace();  
        } finally{
            try {
            	in.close();
				out.close();
			} catch (IOException e) {
				e.printStackTrace();
			}
        } 
	}
	/**
	 * 判断文件是否为图片<br>
	 * <br>
	 * 
	 * @param filename
	 *            文件名<br>
	 *            判断具体文件类型<br>
	 * @return 检查后的结果<br>
	 * @throws Exception
	 */
//	public static boolean isPicture(String filename) {
//		// 文件名称为空的场合
//		if (oConvertUtils.isEmpty(filename)) {
//			// 返回不和合法
//			return false;
//		}
//		// 获得文件后缀名
//		//String tmpName = getExtend(filename);
//		String tmpName = filename;
//		// 声明图片后缀名数组
//		String imgeArray[][] = { { "bmp", "0" }, { "dib", "1" },
//				{ "gif", "2" }, { "jfif", "3" }, { "jpe", "4" },
//				{ "jpeg", "5" }, { "jpg", "6" }, { "png", "7" },
//				{ "tif", "8" }, { "tiff", "9" }, { "ico", "10" } };
//		// 遍历名称数组
//		for (int i = 0; i < imgeArray.length; i++) {
//			// 判断单个类型文件的场合
//			if (imgeArray[i][0].equals(tmpName.toLowerCase())) {
//				return true;
//			}
//		}
//		return false;
//	}

	/**
	 * 判断文件是否为DWG<br>
	 * <br>
	 * 
	 * @param filename
	 *            文件名<br>
	 *            判断具体文件类型<br>
	 * @return 检查后的结果<br>
	 * @throws Exception
	 */
//	public static boolean isDwg(String filename) {
//		// 文件名称为空的场合
//		if (oConvertUtils.isEmpty(filename)) {
//			// 返回不和合法
//			return false;
//		}
//		// 获得文件后缀名
//		String tmpName = getExtend(filename);
//		// 声明图片后缀名数组
//		if (tmpName.equals("dwg")) {
//			return true;
//		}
//		return false;
//	}
	

	/**
	 * 获取rootFileName文件夹中的所有文件名称，并放入filesNameList
	 * @param rootFileName 
	 * @param filesNameList 
	 * @author cjianquan
	 * 2015-2-5
	 */
	public static void getFilesName(String rootFileName,List<String> filesNameList){
		
		File rootRile = new File(rootFileName);
		File[] fileArr = rootRile.listFiles();
		for(int i=0,len=fileArr.length;i<len;i++){
			File file = fileArr[i];
			if(file.isFile()){
				filesNameList.add(file.getAbsolutePath());
			}else if(file.isDirectory()){
				getFilesName(file.getAbsolutePath(),filesNameList);
			}
		}
	}
	
	/**
	 * 单个文件（夹）的压缩，支持文件名为中文条件下
	 * @param inFile 要压缩的文件全路径
	 * @param zipFile 压缩后的压缩包全路径名称
	 * @return
	 * @author cjianquan
	 * 2015-2-5
	 */
	public static void zipFileCompress(String inFile, String zipFile){
		ZipOutputStream out = null;
		try {
			CheckedOutputStream cusm = new CheckedOutputStream(
					new FileOutputStream(zipFile), new Adler32());
			out = new ZipOutputStream(new BufferedOutputStream(cusm));

			fileZip(new File(inFile), out, "");
		} catch (IOException e) {
			e.printStackTrace();
		} finally {
			if (out != null) {
				try {
					out.close();
				} catch (IOException e) {
					e.printStackTrace();
				}
			}
		}
	}
	
	/**
	 * 对单个文件（夹）的具体压缩过程
	 * 
	 * @param file 要压缩的文件全路径
	 * @param out 要压缩文件的字节流
	 * @param base 1、如果是文件形式：文件名称的替换，默认为原文件名，可改为文件夹+新文件名形式，如“a.doc”改为“合同书\\123.doc”
	 * 			   2、如果是文件夹形式：是路径形式，如“合同书\\”（不是很确定）
	 * @throws IOException
	 * @return void
	 * @author: cwq@linewell.com
	 * @data:2014-2-19
	 */
	private static void fileZip(File file, ZipOutputStream out, String base)
			throws IOException {
		if(file.exists()){
			if (file.isFile()) {
				if (base.length() > 0) {
					out.putNextEntry(new ZipEntry(base));
				} else {
					out.putNextEntry(new ZipEntry(file.getName()));
				}

				BufferedReader in = new BufferedReader(new InputStreamReader(
						new FileInputStream(file), "ISO8859_1"));

				int c;
				while ((c = in.read()) != -1) {
					out.write(c);
				}
				in.close();

			} else if (file.isDirectory()) {
				File[] subFiles = file.listFiles();

				out.putNextEntry(new ZipEntry(base + File.separator));
				base = base.length() != 0 ? base + File.separator : "";

				for (File subFile : subFiles) {
					fileZip(subFile, out, base + subFile.getName());
				}
			}
		}else{
			System.out.println("系统找不到指定文件："+file.toString());
		}
	}
	
	/**
	 * 使用给定密码解压zip文件到目录outDir
	 * @param inFile
	 * @param outDir
	 * @param pwd 
	 * @param msFileList 解压文件的文件列表
	 * @throws SevenZipException 
	 * @throws FileNotFoundException
	 * @author cjianquan
	 * 2015-2-6
	 * @throws SevenZipException 
	 * @throws FileNotFoundException 
	 */
	public static void unZipWithPwd(String inFile, String outDir, String pwd,List<String> msFileList)
			throws  SevenZipException, FileNotFoundException {
		
		final String sourceZipFile = inFile;
		final String destinationDir = outDir;

		RandomAccessFile randomAccessFile = null;
		ISevenZipInArchive inArchive = null;
	
			randomAccessFile = new RandomAccessFile(sourceZipFile, "r");
			inArchive = SevenZip.openInArchive(null, // autodetect archive type
					new RandomAccessFileInStream(randomAccessFile));

			// Getting simple interface of the archive inArchive
			ISimpleInArchive simpleInArchive = inArchive.getSimpleInterface();

			for (final ISimpleInArchiveItem item : simpleInArchive
					.getArchiveItems()) {
				final int[] hash = new int[] { 0 };
				if (!item.isFolder()) {
					ExtractOperationResult result;
					result = item.extractSlow(new ISequentialOutStream() {
						public int write(final byte[] data)
								throws SevenZipException {
							try {
								if (item.getPath().indexOf(File.separator) > 0) {
									String path = destinationDir
											+ File.separator
											+ item.getPath().substring(
													0,
													item.getPath().lastIndexOf(
															File.separator));
									File folderExisting = new File(path);
									if (!folderExisting.exists())
										new File(path).mkdirs();
								}
								if (!new File(destinationDir + File.separator
										+ item.getPath()).exists()) {
									new File(destinationDir).createNewFile();
								}
								OutputStream out = new FileOutputStream(
										destinationDir + File.separator
												+ item.getPath());
								out.write(data);
								
//								int iOutcome = 0;
//								byte bLoop;
//								
//								for(int i=0;i<data.length;i++){
//									bLoop = data[i];
//									iOutcome+=(bLoop & 0xFF)<<(8*i);
//									out.write(iOutcome);
//								}
									
								
								out.close();
								
//								OutputStreamWriter osw = new OutputStreamWriter(out,"UTF-8");
//								String dataStr = new String(data,"ISO-8859-1");
//								osw.write(dataStr,0,dataStr.length());
//								osw.flush();
//								osw.close();
								
							} catch (Exception e) {
								e.printStackTrace();
							}
							hash[0] |= Arrays.hashCode(data);
							return data.length; // Return amount of proceed data
						}
					}, pwd); // / password.
					if (result == ExtractOperationResult.OK) {
						if(msFileList!=null){
							msFileList.add(item.getPath());
						}
						System.out.println(String.format("%9X | %s", hash[0],
								item.getPath()));
					} else {
						System.err.println("Error extracting item: " + result);
					}
				}
			}
		
			if (inArchive != null) {
				try {
					inArchive.close();
				} catch (SevenZipException e) {
					System.err.println("Error closing archive: " + e);
					e.printStackTrace();
				}
			}
			if (randomAccessFile != null) {
				try {
					randomAccessFile.close();
				} catch (IOException e) {
					System.err.println("Error closing file: " + e);
					e.printStackTrace();
				}
			}
		

	}
	
	
	/**
	 * 获取在指定日期updateDate后修改过的文件列表
	 * 文件名放入resultFileNameList
	 * @param rootFile webRoot的路径
	 * @param asideFile 去除的文件目录
	 * @param updateDate 更新的日期
	 * @param resultFileNameList 更新的文件清单
	 * @author cjianquan
	 * 2015-2-6
	 */
	public static void getUpdateFiles(String rootFile,String asideFile,Date updateDate,List<String> resultFileNameList){
		File rFile = new File(rootFile);
		File[] fileArr = rFile.listFiles();
		long lastModifiedTime = 0;
		Date lastModifiedDate = null;
		for(File file:fileArr){
			//如果文件夹包括去除的目录，则跳过
			if(!"".equals(asideFile) && file.getAbsolutePath().matches(asideFile)){
				continue;
			}
			if(file.isDirectory()){//是目录，则递归查找该目录
				getUpdateFiles(file.getAbsolutePath(),asideFile,updateDate,resultFileNameList);
			}else if(file.isFile()){//是文件
				lastModifiedTime = file.lastModified();
				lastModifiedDate = new Date(lastModifiedTime);
				if(updateDate.compareTo(lastModifiedDate)<0){//最后更新时间大于给定的时间
					//文件名称放进resultFileNameList
					resultFileNameList.add(file.getAbsolutePath());
					System.out.println(file.getAbsolutePath());
				}
			}
		}
	}
	
	
	
	 /**
	  * 使用给定密码解压指定压缩文件到指定目录
	  * @param inFile 指定Zip文件
	  * @param outDir 解压目录
	  * @param passwd 解压密码
	  */
//	public static void unzip(String inFile, String outDir, String passwd) {
//		File outDirectory = new File(outDir);
//		if (!outDirectory.exists()) {
//			outDirectory.mkdir();
//		}
//		AESDecrypter decrypter = new AESDecrypterBC();
//		AesZipFileDecrypter zipDecrypter = null;
//		try {
//			zipDecrypter = new AesZipFileDecrypter(new File(inFile), decrypter);
//			AesZipFileDecrypter.charset = "utf-8";
//			/**
//			 * 得到ZIP文件中所有Entry,但此处好像与JDK里不同,目录不视为Entry
//			 * 需要创建文件夹,entry.isDirectory()方法同样不适用,不知道是不是自己使用错误 处理文件夹问题处理可能不太好
//			 */
//			List<ExtZipEntry> entryList = zipDecrypter.getEntryList();
//			for (ExtZipEntry entry : entryList) {
//				String eName = entry.getName();
//				String dir = eName.substring(0,
//						eName.lastIndexOf(File.separator) + 1);
//				File extractDir = new File(outDir, dir);
//				if (!extractDir.exists()) {
//					FileUtils.forceMkdir(extractDir);
//				}
//				/**
//				 * 抽出文件
//				 */
//				File extractFile = new File(outDir + File.separator + eName);
//				zipDecrypter.extractEntry(entry, extractFile, passwd);
//			}
//		} catch (IOException e) {
//			e.printStackTrace();
//		} catch (DataFormatException e) {
//			e.printStackTrace();
//		} finally {
//			try {
//				zipDecrypter.close();
//			} catch (IOException e) {
//				e.printStackTrace();
//			}
//		}
//	}
	
    public static void unzip(File zipFile, String dest, String passwd) throws ZipException {  
        ZipFile zFile = new ZipFile(zipFile);  // 首先创建ZipFile指向磁盘上的.zip文件  
        zFile.setFileNameCharset("GBK");       // 设置文件名编码，在GBK系统中需要设置  
        if (!zFile.isValidZipFile()) {   // 验证.zip文件是否合法，包括文件是否存在、是否为zip文件、是否被损坏等  
            throw new ZipException("压缩文件不合法,可能被损坏.");  
        }  
        File destDir = new File(dest);     // 解压目录  
        if (destDir.isDirectory() && !destDir.exists()) {  
            destDir.mkdir();  
        }  
        if (zFile.isEncrypted()) {  
            zFile.setPassword(passwd.toCharArray());  // 设置密码  
        }  
        zFile.extractAll(dest);      // 将文件抽出到解压目录(解压)  
    }  
    
	
	public static void main(String[] args) throws Exception{
//		String ss="D:/workspace/web/WebRoot/WEB-INF/classes/com/linewell/controller/common/VersionController.class";
//		String reg = "WEB.INF.classes.*";
//		if(ss.matches(reg)){
//			System.out.println("match");
//		}else{
//			System.out.println("not match");
//		}
		
		unzip(new File("E:\\testZip.zip"),"E:\\testZip","123");
		
	}
	
	
	
}
